package com.vshop.framework.mybatisflex.datapermission;

import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.vshop.framework.core.spring.SpringContextUtil;
import com.vshop.framework.mybatisflex.context.DataPermissionUserContextProvider;
import com.vshop.framework.mybatisflex.context.RoleContext;
import com.vshop.framework.mybatisflex.context.UserContext;

import java.util.List;

import static com.mybatisflex.core.query.QueryMethods.bracket;
import static com.mybatisflex.core.query.QueryMethods.select;
import static com.vshop.framework.mybatisflex.datapermission.DataPermTableField.*;

public class DataPermHelper {

    // 全部数据权限
    public static final String DATA_SCOPE_ALL = "1";
    // 自定数据权限
    public static final String DATA_SCOPE_CUSTOM = "2";
    // 部门数据权限
    public static final String DATA_SCOPE_DEPT = "3";
    // 部门及以下数据权限
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
    // 仅本人数据权限
    public static final String DATA_SCOPE_SELF = "5";


    /**
     * 添加数据权限条件
     *
     * @param queryWrapper 查询条件
     */
    public static QueryWrapper buildDataScope(QueryWrapper queryWrapper) {
        DataPermissionUserContextProvider userContextProvider = SpringContextUtil.getBean(DataPermissionUserContextProvider.class);
        UserContext userContext = userContextProvider.getUserContext();
        // 如果是超级管理员，则不过滤数据
        if (ObjectUtil.isNull(userContext) || userContext.isSuperAdmin()) {
            return queryWrapper;
        }
        List<RoleContext> roles = userContext.getRoles();
        //生成数据权限, 除了“2：自定义数据权限”，其它值去重存入dataScopeList列表
        List<String> dataScopeList = roles.stream()
                .map(RoleContext::getDataScope)
                .filter(dataScope -> !DATA_SCOPE_CUSTOM.equals(dataScope))
                .distinct()
                .toList();

        //1.查询全部数据
        if (dataScopeList.contains(DATA_SCOPE_ALL)) {
            return queryWrapper;
        }

        QueryCondition queryCondition = QueryCondition.createEmpty();
        //2.查询自定义数据
        for (String dataScope : dataScopeList) {
            if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
                for (RoleContext role : roles) {
                    //SQL: or sys_dept.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE sys_role_dept.role_id = #{roleId} )
                    queryCondition
                            .or(new QueryColumn(DeptTableName, DeptId).in(
                                    select(new QueryColumn(RoleDeptTableName, DeptId))
                                            .from(RoleDeptTableName)
                                            .where(new QueryColumn(RoleDeptTableName, RoleId).eq(role.getRoleId()))
                            ));
                }
            }
        }

        //3.查询本部门数据
        if (dataScopeList.contains(DATA_SCOPE_DEPT)) {
            //SQL: or sys_dept.dept_id = #{roleId}
            queryCondition.or(new QueryColumn(DeptTableName, DeptId).eq(userContext.getDeptId()));
        }

        //4.查询本部门及以下数据
        if (dataScopeList.contains(DATA_SCOPE_DEPT_AND_CHILD)) {
            //SQL: or sys_dept.dept_id IN ( SELECT dept_id FROM sys_dept WHERE sys_dept.dept_id = #{deptId} or find_in_set(#{deptId} , sys_dept.ancestors)
            queryCondition.or(new QueryColumn(DeptTableName, DeptId)
                    .in(select(new QueryColumn(DeptTableName, DeptId))
                            .from(DeptTableName)
                            .where(new QueryColumn(DeptTableName, DeptId).eq(userContext.getDeptId()))
                            .or(QueryMethods.findInSet(QueryMethods.number(userContext.getDeptId()),
                                    new QueryColumn(DeptTableName, "ancestors")).gt(0))));
        }


        //5.查询本人数据
        if (dataScopeList.contains(DATA_SCOPE_SELF)) {
            //OR sys_user.user_id = #{userId}
            queryCondition.or(new QueryColumn(UserTableName, UserId).eq(userContext.getUserId()));
        }

        //所有新增的查询条件外边用圆括号包括起来
        queryWrapper.and(bracket(queryCondition));

        return queryWrapper;
    }

}
